package jeme.lang;

/**
 *
 *
 * @author Erik Silkensen (silkense@colorado.edu)
 * @version Aug 13, 2009
 */
public class SchemePair extends SchemeObject
{
    /**
     * 
     */
    public static final SchemePair EMPTY_LIST = new SchemePair(null, null);
    
    private SchemeObject car, cdr;
    
    /**
     * 
     * @param car
     * @param cdr
     */
    public SchemePair(SchemeObject car, SchemeObject cdr)
    {
        setCar(car);
        setCdr(cdr);
    }
    
    /**
     * 
     * @return
     */
    public SchemeObject car()
    {
        return car;
    }
    
    /**
     * 
     * @return
     */
    public SchemeObject cdr()
    {
        return cdr;
    }
    
    /**
     * 
     * @param car
     */
    public void setCar(SchemeObject car)
    {
        this.car = car;
    }
    
    /**
     * 
     * @param cdr
     */
    public void setCdr(SchemeObject cdr)
    {
        this.cdr = cdr;
    }
    
    /**
     * 
     * @return
     */
    public boolean isPair()
    {
        return true;
    }
    
    /**
     * 
     * @return
     */
    public boolean isList()
    {
        SchemeObject cdr = this.cdr;
        
        while (cdr instanceof SchemePair) {
            cdr = ((SchemePair) cdr).cdr();
        }
        
        return cdr == null;
    }
    
    /**
     * 
     * @return
     */
    public boolean isNull()
    {
        return car == null && cdr == null;
    }
    
    /*
     * (non-Javadoc)
     * @see java.lang.Object#equals(java.lang.Object)
     */
    public boolean equals(Object other)
    {
        if (other instanceof SchemePair) {
            SchemePair pair = (SchemePair) other;
            boolean careq, cdreq;
            
            if (car == null) {
                careq = pair.car == null;
            } else {
                careq = car.equals(pair.car);
            }
            
            if (cdr == null) {
                cdreq = pair.cdr == null;
            } else {
                cdreq = cdr.equals(pair.cdr);
            }
            
            return careq && cdreq;
        } else {
            return false;
        }
    }
    
    /*
     * (non-Javadoc)
     * @see jeme.lang.SchemeObject#toString()
     */
    public String toString()
    {
        String ext = "(";
        
        SchemeObject it = this;
        while (it instanceof SchemePair) {
            SchemePair pair = (SchemePair) it;
            
            ext += pair.car == null ? "" : pair.car;
            if (pair.cdr instanceof SchemePair) {
                ext += pair.cdr == EMPTY_LIST ? "" : " ";
            } else if (pair.cdr != null) {
                ext +=  " . " + pair.cdr;
            }
            
            it = pair.cdr;
        }
        
        return ext + ")";
    }
    
    /*
     * (non-Javadoc)
     * @see jeme.lang.SchemeObject#toDisplayString()
     */
    public String toDisplayString()
    {
        String ext = "(";
        
        SchemeObject it = this;
        while (it instanceof SchemePair) {
            SchemePair pair = (SchemePair) it;
            
            ext += pair.car == null ? "" : pair.car.toDisplayString();
            if (pair.cdr instanceof SchemePair) {
                ext += pair.cdr == EMPTY_LIST ? "" : " ";
            } else if (pair.cdr != null) {
                ext +=  " . " + pair.cdr.toDisplayString();
            }
            
            it = pair.cdr;
        }
        
        return ext + ")";
    }
}
